programming4us
           
 
 
Programming

iPad SDK : Outputting to an External Screen

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
11/13/2010 3:58:37 PM
The UIScreen class has been a part of iOS since the beginning. Its mainScreen class method gives you the screen of the device you're running on, which you can query for geometry information such as its bounds or frame.

In iOS 3.2, UIScreen gets a new class method, screens, which returns an array of all currently connected screens, including the iPad's own screen. This is the key to accessing an attached external screen. If it contains more than one item, all but the first are external screens. Also new in iOS 3.2 is the ability to ask any screen which resolutions it supports via the availableModes method, along with the currentMode method for determining and setting which resolution is in use.

You can move any of your content to an external screen simply by creating a new UIWindow object, adding your views to it, and setting its screen property to point to the external screen.

1. Extending the Video App to Handle an External Screen

When using an external screen, you need to consider how to properly handle when the user plugs in or unplugs a screen. To help with this, UIScreen defines a few notifications that let you know when a screen is connected or disconnected, so you can act accordingly.

In this section, we'll extend our VideoToy project so that if a screen is connected, the video you choose will play on it; if you disconnect the screen, the video will continue playing on the device. This will require a bit of extra bookkeeping on our part—we'll need to keep track of the currently selected video and its corresponding views, so that we can switch things around as the external screen comes and goes.

Start off by editing VideoCell.h, adding a few lines to define a delegate, a protocol the delegate should implement, and a property declaration for movieViewContainer so that we can reach it from other classes.

//  VideoCell.h
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
@interface VideoCell : UITableViewCell {
IBOutlet UIView *movieViewContainer;
IBOutlet UILabel *urlLabel;
NSString *urlPath;
MPMoviePlayerController *mpc;
id delegate;
}
@property (retain, nonatomic) UIView *movieViewContainer;
@property (retain, nonatomic) NSString *urlPath;
@property (retain, nonatomic) MPMoviePlayerController *mpc;
@property (assign, nonatomic) id delegate;
+ (NSString *)reuseIdentifier;
+ (CGFloat)rowHeight;
@end
@protocol VideoCellDelegate
- (void)videoCellStartedPlaying:(VideoCell *)cell;
@end

Now switch to VideoCell.m, and add synthesized accessors for movieViewContainer and delegate.

@synthesize urlPath, mpc, movieViewContainer, delegate;

Then free up one additional resource in dealloc:

- (void)dealloc {
self.urlPath = nil;
self.mpc = nil;
self.movieViewContainer = nil;
[super dealloc];
}

Next, implement the following change, to let the delegate know when the video has been selected. This way, the view can be shifted to the external screen (if it's connected).

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if ([delegate respondsToSelector:@selector(videoCellStartedPlaying:)]) {
[delegate videoCellStartedPlaying:self];
}
// Configure the view for the selected state
[mpc play];
}

We really didn't do too much here. The most interesting part—handling a user selection that should put the video on the externalScreen—has been foisted off on a vaguely defined delegate object. Let's make that a bit more concrete, by having VideoToyViewController act as the delegate for VideoCell. This controller will now keep track of the selected VideoCell instance, as well as a UIWindow assigned to an external screen, if there is one.

Open VideoToyViewController.h, and make the changes shown here:

//  VideoToyViewController.h
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
@class VideoCell;
@interface VideoToyViewController : UITableViewController {
NSMutableArray *urlPaths;
IBOutlet VideoCell *videoCell;
UIWindow *externalWindow;
VideoCell *selectedCell;
}
@property (retain, nonatomic) NSMutableArray *urlPaths;
@property (retain, nonatomic) UIWindow *externalWindow;
@property (retain, nonatomic) VideoCell *selectedCell;
@end

Now it's time for VideoToyViewController.m, which is where the real work of managing the external screen happens. Synthesize the new properties, like this:

@synthesize urlPaths, externalWindow, selectedCell;

And make sure that resources are properly freed:

- (void)dealloc {
self.urlPaths = nil;
self.externalWindow = nil;
self.selectedCell = nil;
[super dealloc];
}

Next, move on to the viewDidLoad method. Here, we're going to first call the updateExternalWindow method (which we'll define in just a moment). We'll also set up notifications whenever an external screen is connected or disconnected. Both of these events will also call the updateExternalWindow method.

- (void)viewDidLoad {
[super viewDidLoad];
[self updateExternalWindow];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateExternalWindow)

name:UIScreenDidConnectNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateExternalWindow)
name:UIScreenDidDisconnectNotification
object:nil];
}

And now for the updateExternalWindow method itself. As you just saw, this method is called when our view is loaded, as well as every time the external screen is connected or disconnected. It's fairly complicated, since it is designed to handle the variety of situations it may encounter and do the right thing. The comments in the code provide more details.

- (void)updateExternalWindow {
if ([[UIScreen screens] count] > 1) {
//
// An external screen is connected. Find the screen, put a
// UIWindow on it.
//
UIScreen *externalScreen = [[UIScreen screens] lastObject];
// Screen modes are sorted in order of increasing resolution.
// Let's take the highest.
UIScreenMode *highestScreenMode = [[externalScreen availableModes]
lastObject];
CGRect externalWindowFrame = CGRectMake(0, 0,
[highestScreenMode size].width, [highestScreenMode size].height);
self.externalWindow = [[[UIWindow alloc] initWithFrame:
externalWindowFrame] autorelease];
externalWindow.screen = externalScreen;
[externalWindow.screen setCurrentMode:highestScreenMode];
[externalWindow makeKeyAndVisible];
if (selectedCell) {
// A cell is selected. Move its view to the external window.
[externalWindow addSubview:selectedCell.mpc.view];
selectedCell.mpc.view.frame = externalWindow.bounds;
}
} else if ([[UIScreen screens] count] == 1) {
//
// No external screen is connected. Let's make sure we have no
// dangling references
// to anything off the main screen.
//
if ([[externalWindow subviews] count] > 0) {
// externalWindow used to be attached to a screen which is no
// longer there! Move its view back to where it came from.
UIView *v = [[externalWindow subviews] lastObject];
v.frame = selectedCell.movieViewContainer.bounds;
[selectedCell.movieViewContainer addSubview:v];
}
self.externalWindow.screen = nil;
self.externalWindow = nil;
}
}


NOTE

The updateExternalWindow method could have been split into three methods: one for each of the notifications, and one for after the nib file loaded. In fact, the first version I wrote did just that. But I noticed there was some functional overlap, so I refactored a bit. To me, it seems that compressing it into one method brings it together a bit better.

The next thing to tackle is the creation of the VideoCell instances. Each needs to be told who its delegate is. Find the relevant section in tableView:cellForRowAtIndexPath:, and add the bold line shown here:

[[NSBundle mainBundle] loadNibNamed:@"VideoCell" owner:self
options:nil];
cell = videoCell;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.delegate = self;

2. Implementing the VideoCell Delegate Method

Finally, let's implement the delegate method itself. As you may recall, this method is called whenever the user selects a VideoCell in the GUI. Here, we need to check whether an external screen is connected and whether another video is currently running. Yes, this method is even more complicated than the updateExternalWindow method, but it has a lot to do. Again, the code comments provide more explanation.

- (void)videoCellStartedPlaying:(VideoCell *)cell {
if (selectedCell != cell) { // Skip everything if it's the same cell.
if ([[UIScreen screens] count] > 1) {
// Switching external from one video (or blank) to another
UIScreen *externalScreen = [[UIScreen screens] lastObject];
UIScreenMode *highestScreenMode = [[externalScreen availableModes]
lastObject];
CGRect externalWindowFrame = CGRectMake(0, 0,
[highestScreenMode size].width, [highestScreenMode size].height);
if ([[externalWindow subviews] count] > 0) {
// There's already a movie there. Put its view back in the cell
// it came from.
UIView *v = [[externalWindow subviews] lastObject];
v.frame = selectedCell.movieViewContainer.bounds;
[selectedCell.movieViewContainer addSubview:v];
}
// We're done with the old movie and cell.
self.selectedCell = cell;
// Get rid of the old window and screens; create new ones.
self.externalWindow = [[[UIWindow alloc] initWithFrame:
externalWindowFrame] autorelease];
externalWindow.screen = externalScreen;
[externalWindow.screen setCurrentMode:highestScreenMode];
[externalWindow makeKeyAndVisible];
if (selectedCell) {
// Move the selected cell's movie view to the external screen.


[externalWindow addSubview:selectedCell.mpc.view];
selectedCell.mpc.view.frame = externalWindow.bounds;
}
} else if ([[UIScreen screens] count] == 1) {
// No external screen is connected.
if ([[externalWindow subviews] count] > 0) {
// We seem to have an old external window hanging around. Move
// its view back to the cell it came from.
UIView *v = [[externalWindow subviews] lastObject];
v.frame = selectedCell.movieViewContainer.bounds;
[selectedCell.movieViewContainer addSubview:v];
}
self.externalWindow.screen = nil;
self.externalWindow = nil;
// Keep track of the selected cell.
self.selectedCell = cell;
}
}
}

3. Testing the External Screen Functionality

Now build and run the app, and then unplug your iPad from your computer. This will probably crash the app, but that's OK.

Start up the app again directly on the iPad. Now whip out your trusty iPad-VGA adapter, find a convenient monitor with a VGA input, and plug it in. If you do that while a video is playing, you'll see that the video jumps to the external monitor. Otherwise, start playing a video, and you'll see it appear there.

The code we wrote for this functionality is quite robust. You should be able to unplug and reattach the screen during playback, before starting playback, while switching songs, before launching the app, and so on. You'll find that "it just works."

Other -----------------
- iPad SDK : Displaying Multiple Videos
- Parallel Programming Drivers
- Parallel Programming with Microsoft .Net : Parallel Loops - An Example
- Parallel Programming with Microsoft .Net : Parallel Loops - The Basics
- What is New in iPhone SDK 3.2 for the iPad (part 2)
- What is New in iPhone SDK 3.2 for the iPad (part 1)
- Programming with DirectX : Rendering Geometry - Colors
- ASP.NET Security : The Membership and Role Management API (part 3) - Role
- ASP.NET Security : The Membership and Role Management API (part 2) - Provider
- ASP.NET Security : The Membership and Role Management API (part 1)
- ASP.NET Security : Security-Related Controls (part 2)
- ASP.NET Security : Security-Related Controls (part 1)
- WCF Security Concepts
- Certificate-Based Encryption
- Encryption Using SSL
- Security Privileges and Services
- Client Credentials
- User-Level Security : Service Credentials
- User-Level Security : Custom Authentication
- User-Level Security : Authorization and Impersonation (part 4) - Impersonation
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us